//
//  ZBNavigator.m
//  ZBNavigator
//
//  Created by xzb on 2018/5/30.
//

#import "ZBNavigator.h"
#import <ZBYAML/YAMLSerialization.h>

@interface ZBNavigator ()

@property (nonatomic, strong) ZBNavigationController *currentNavigationController;

@property (nonatomic, strong) UIViewController *topVisibleViewController;

@end


@implementation ZBNavigator

+ (instancetype)instance
{
    static dispatch_once_t oncePredicate;
    static id instance;
    dispatch_once(&oncePredicate, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (BOOL)canPushViewController:(UIViewController *)viewController
{
    if (!viewController) {
        return NO;
    }
    if (![[self currentViewController] isKindOfClass:[UINavigationController class]]) {
        return NO;
    }
    return YES;
}

- (BOOL)pushViewController:(UIViewController *)viewController animated:(BOOL)animate
{
    if (![self canPushViewController:viewController]) {
        return NO;
    }
    [self.currentNavigationController pushViewController:viewController animated:animate];
    return YES;
}

- (BOOL)canPopViewController
{
    if (self.currentNavigationController.viewControllers.count <= 1) {
        return NO;
    }
    return YES;
}

- (BOOL)popViewControllerAnimated:(BOOL)animate
{
    if (![self canPopViewController]) {
        return NO;
    }
    ZBNavigationController *navigationController = self.currentNavigationController;
    if (navigationController.presentedViewController) {
        [navigationController dismissViewControllerAnimated:NO completion:^{
            [navigationController popViewControllerAnimated:animate];
        }];
        return YES;
    }
    [navigationController popViewControllerAnimated:animate];
    return YES;
}

- (BOOL)canPopToViewController:(UIViewController *)viewController animated:(BOOL)animate
{
    ZBNavigationController *navigationController = self.currentNavigationController;
    if (!navigationController || navigationController.topVisibleViewController != navigationController.topViewController) {
        return NO;
    }
    return YES;
}
- (BOOL)popToViewController:(UIViewController *)viewController animated:(BOOL)animate
{
    if (![self canPopToViewController:viewController animated:animate]) {
        return NO;
    }
    ZBNavigationController *navigationController = self.currentNavigationController;
    if (navigationController.presentedViewController) {
        [navigationController dismissViewControllerAnimated:NO completion:^{
            [navigationController popToViewController:viewController animated:animate];
        }];
        return YES;
    }
    [navigationController popToViewController:viewController animated:animate];
    return YES;
}

- (BOOL)canPresentViewController:(UIViewController *)viewController animated:(BOOL)animate completion:(void (^)(void))completion
{
    if (!viewController) {
        return NO;
    }
    return YES;
}

- (BOOL)presentViewController:(UIViewController *)viewController  animated:(BOOL)animate completion:(void (^)(void))completion
{
    if (![self canPresentViewController:viewController animated:animate completion:nil]) {
        return NO;
    }
    id obj = [self currentViewController];
    if ([obj isKindOfClass:[ZBNavigationController class]]) {
        [[(ZBNavigationController *)obj topVisibleViewController] presentViewController:viewController animated:animate completion:completion];
        return YES;
    } else if ([obj isKindOfClass:[UIViewController class]]) {
        [(UIViewController *)obj presentViewController:viewController animated:animate completion:completion];
    }
    return NO;
}

- (BOOL)canDismissViewController:(BOOL)animate completion:(void (^)(void))completion
{
    return YES;
}

- (BOOL)dismissViewController:(BOOL)animate completion:(void (^)(void))completion
{
    if (![self canDismissViewController:animate completion:nil]) {
        return NO;
    }
    ZBNavigationController *navigationController = self.currentNavigationController;
    if ([navigationController isKindOfClass:[UIViewController class]]) {
        [navigationController dismissViewControllerAnimated:animate completion:completion];
        return YES;
    }
    UIViewController *modalViewController = navigationController.topVisibleViewController;
    [modalViewController dismissViewControllerAnimated:animate completion:completion];
    return YES;
}


- (UIViewController *)currentViewController
{
    UIWindow *keyWindow  = [UIApplication sharedApplication].keyWindow;
    UIViewController *vc = keyWindow.rootViewController;
    while (vc.presentedViewController)
    {
        vc = vc.presentedViewController;
        
        if ([vc isKindOfClass:[UINavigationController class]])
        {
            vc = [(UINavigationController *)vc visibleViewController];
        }
        else if ([vc isKindOfClass:[UITabBarController class]])
        {
            vc = [(UITabBarController *)vc selectedViewController];
        }
    }
    return vc;
}

- (ZBNavigationController *)currentNavigationController
{
    id obj = [self currentViewController];
    if (![[obj class] isSubclassOfClass:[UIViewController class]]) {
        return nil;
    }
    if ([[obj class] isSubclassOfClass:[UINavigationController class]]) {
        return obj;
    }
    if ([[obj class] isSubclassOfClass:[UITabBarController class]]) {
        id subObj = [(UITabBarController *)obj selectedViewController];
        if ([[subObj class] isSubclassOfClass:[UINavigationController class]]) {
            return subObj;
        }
        if ([[subObj class] isSubclassOfClass:[UIViewController class]]) {
            return (ZBNavigationController *)[self currentViewController].navigationController;
        }
    }
    return obj;
}

+ (BOOL)registerRoute
{
    NSURL *pathURL = [[NSBundle mainBundle] URLForResource:@".ALL_TARGETS" withExtension:@"yml"];
    if (pathURL.absoluteString.length < 1) {
        NSLog(@"⚠️ 请检查 ${SRCROOT}/bin/generate_targets 脚本配置 和 run Script 是否配置;准备降级,只读主工程的targets");
        NSURL *mainURL = [[NSBundle mainBundle] URLForResource:@"targets" withExtension:@"yaml"];
        if (mainURL.absoluteString.length < 1) {
            NSLog(@"❌ 主工程缺少targets.yaml 文件, registerRoute 失败");
            return NO;
        }
        pathURL = mainURL;
    }
    NSData *routesData = [NSData dataWithContentsOfURL:pathURL options:NSDataReadingMappedIfSafe | NSDataReadingUncached error:nil];
    NSDictionary  *targets  =  [YAMLSerialization objectWithYAMLData:routesData options:0 error:nil];
    if (!targets) {
        return NO;
    }
    for (NSString *controller in targets.allKeys) {
        NSDictionary *targetsDict = targets[controller];
        NSArray *targets = targetsDict[@"targets"];
        NSString *target = [targets firstObject];
        [ZBRouter registerURLPattern:target toHandler:^(NSDictionary *routerParameters) {
            [ZBNavigator openControllerWithControllStr:controller param:routerParameters];
        }];
    }
    return YES;
}
+ (void)openControllerWithControllStr:(NSString *)controller param:(NSDictionary *)routerParameters
{
    Class vcClass =  NSClassFromString(controller);
    if (!vcClass) {
        NSLog(@"❌ < %@ Class> is nil",controller);
        return;
    }
    UIViewController *vc = [[NSClassFromString(controller) alloc] init];
    vc.zbPageResultBlock = routerParameters[ZBRouterParameterCompletion];
    vc.params = routerParameters;
    if (![vc canOpenControllerWithParams:routerParameters]) {
        if (vc.zbPageResultBlock) {
            vc.zbPageResultBlock(@{@"result":@(NO), @"message" : @"❌ 跳转失败,检查参数",@"params":routerParameters});
        }
        return;
    }
    BOOL animated = YES;
    if ([routerParameters.allKeys containsObject:@"animated"]) {
        animated = [routerParameters[@"animated"] boolValue];
    }
    if ([[ZBNavigator instance] canPushViewController:vc]) {
        [[ZBNavigator instance] pushViewController:vc animated:animated];
    } else if ([[ZBNavigator instance] canPresentViewController:vc animated:animated completion:nil]){
        [[ZBNavigator instance] presentViewController:vc animated:animated completion:nil];
    }
}
@end
